﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace CorporationWars
{
    [Serializable]
    public class UIControlBase
    {
        [NonSerialized]
        public Game1 Game;

        protected SpriteBatch spriteBatch { get { return (SpriteBatch)Game.Services.GetService(typeof(SpriteBatch)); } }

        public virtual int Width { get; set; }
        public virtual int Height { get; set; }

        protected virtual Rectangle BGRectangle { get { return new Rectangle((int)Position.X, (int)Position.Y, Width, Height); } }

        public virtual Vector2 Position { get; set; }

        public bool IsDragable { get; set; }
        public bool spokeTip { get; set; }

        public string ToolTipText { get; set; }

        private bool _dragging { get; set; }
        public bool Dragging { get { return _dragging; } }

        private List<UIZone> controlsToAdd = new List<UIZone>();
        private List<UIZone> controlsToRemove = new List<UIZone>();
        private List<UIZone> UIControls = new List<UIZone>();

        [NonSerialized]
        public UIEvent OnButtonClicked;

        public UIControlBase(Game1 game, bool baseCloseOn = true)
        {
            Game = game;

            if(baseCloseOn)
                AddControl(new UIButton(game) { TextureAsset = "Textures/HUD/Buttons/cancel", Color = Color.White, HoverColor = Color.Silver, MouseDownColor = Color.LimeGreen, Name = "baseClose", ToolTipText = "Close", Width = 16, Height = 16, OpacityTolerance = 0 });
        }

        public void AddControl(UIZone control, bool imediate = true)
        {
            if (control is UIButton)
            {
                control.OnClick = ButtonClicked;
            }

            if (imediate)
                UIControls.Add(control);
            else
                controlsToAdd.Add(control);
        }

        public void ClearControls(bool imediate = true, params string[] exceptionNames)
        {
            ClearControls<UIZone>(imediate, exceptionNames);
        }

        public void ClearControls<T>(bool imediate = true, params string[] exceptionNames) where T : UIZone
        {
            exceptionNames = CheckExceptions(exceptionNames);

            for (int z = UIControls.Count - 1; z >= 0; z--)
            {
                if (!exceptionNames.Contains(UIControls[z].Name))
                {
                    if (UIControls[z].GetType() == typeof(T) || UIControls[z].GetType().BaseType == typeof(T))
                    {
                        if (imediate)
                            UIControls.Remove(UIControls[z]);
                        else
                            controlsToRemove.Add(UIControls[z]);
                    }
                }
            }
        }

        public string[] CheckExceptions(string[] exceptionNames)
        {
            if (exceptionNames == null)
                exceptionNames = new string[] { "baseClose" };
            else
            {
                List<string> ex = new List<string>(exceptionNames);

                if (!ex.Contains("baseClose"))
                    ex.Add("baseClose");

                exceptionNames = ex.ToArray();
            }

            return exceptionNames;
        }

        public void ClearButtons(bool imediate = true, params string[] exceptionNames)
        {

            ClearControls<UIButton>(imediate, exceptionNames);
        }

        public void ClearControlByName(string name, bool imediate = true)
        {
            if (imediate)
            {
                if (UIControls.SingleOrDefault(c => c.Name == name) != null)
                    UIControls.Remove(UIControls.SingleOrDefault(c => c.Name == name));
            }
            else
                if (UIControls.SingleOrDefault(c => c.Name == name) != null)
                    controlsToRemove.Add(UIControls.SingleOrDefault(c => c.Name == name));
                
        }

        public UIZone GetControl(string name)
        {
            return UIControls.SingleOrDefault(c => c.Name == name);
        }
        
        protected virtual void ButtonClicked(UIZone sender)
        {
            switch (sender.Name)
            {
                case "baseClose":
                    if (OnButtonClicked != null)
                        OnButtonClicked(sender);
                    break;
            }
        }

        private bool updateApplied = false;
        public virtual void Update(GameTime gameTime)
        {
            if (!updateApplied)
                updateApplied = true;

            // add those required.
            foreach (UIZone z in controlsToAdd)
                AddControl(z);

            controlsToAdd.Clear();

            foreach (UIZone control in UIControls)
                control.Update(gameTime);

            if (Game.IsMouseOverRectangle(BGRectangle) || Game1.DraggingControll == this)
            {
                if (!string.IsNullOrEmpty(ToolTipText))
                {
                    if (!spokeTip && Game.AudioOn && Game.SpeechOn)
                    {
                        spokeTip = true;
                        Game.Say(ToolTipText, true);
                    }
                }

                if (IsDragable && Game.LeftButtonHeldDown && (Game.IsMouseOverUIZone == null || !UIControls.Contains(Game.IsMouseOverUIZone)))
                {
                    Game1.DraggingControll = this;
                    Position -= new Vector2(Game.lstptrPos.X, Game.lstptrPos.Y) - new Vector2(Game.ptrPos.X, Game.ptrPos.Y);
                    Position = Vector2.Clamp(Position, Vector2.Zero, new Vector2(Game.GraphicsDevice.Viewport.Width - Width, Game.GraphicsDevice.Viewport.Height - Height));
                }
                else
                    Game1.DraggingControll = null;
            }
            else
                spokeTip = false;

            foreach (UIZone control in UIControls)
            {
                if (control.Name == "baseClose")
                    control.Position = new Vector2(BGRectangle.Left + BGRectangle.Width - 28, BGRectangle.Top + 8);
                else
                    control.Position = Position;
            }

            foreach (UIZone z in controlsToRemove)
                UIControls.Remove(z);

            controlsToRemove.Clear();
            
        }

        public virtual void Draw(GameTime gameTime)
        {
            if (!updateApplied)
                return;

            foreach (UIZone control in UIControls)
                control.Draw(gameTime);
        }        

        public virtual void ReWire(Game1 game)
        {
            Game = game;

            foreach (UIZone control in UIControls)
            {
                if(control is UIButton)
                    control.OnClick = ButtonClicked;
            }
        }

        public virtual void UnWire()
        {
            foreach (UIZone control in UIControls)
            {
                if (control is UIButton)
                    control.OnClick = null;
            }
        }

        public virtual void ReSet()
        {

        }
    }
}
